package com.uh.calculation.util;

import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import static java.lang.StrictMath.abs;
public class Calculator {

private enum Operator {
     ADD("+", 10), SUBTRACT("-", 10), MULTIPLY("*", 20), DIVIDE("/", 20),
     PARENTHESIS_LEFT("(", 100), PARENTHESIS_RIGHT(")", 100),ABS("@", 110);
     private String operator;
     private int priority;
private Operator(String operator, int priority) {
     this.operator = operator;
     this.priority = priority;
}
}
/**
* 枚举
*
*/
private enum Operand {
         ONE("1"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"), SEVEN("7"), EIGHT("8"), NINE("9"), ZERO("0"), POINT(".");
         private String operand;
         private Operand(String operand) {
         this.operand = operand;
         }
}
private Operator getOperator(String str) {
        for (Operator op : Operator.values()) {
        if (str.equals(op.operator)) {
         return op;
        }
        }
        return null;
}
 private Operand getOperand(String str) {
            for (Operand op : Operand.values()) {
            if (str.equals(op.operand)) {
            return op;
            }
            }
            return null;
}

private List<String> resolveExpr(String exp) {
        List<String> list = new LinkedList<String>();
        String temp = "";
        exp = exp.replace(" ", "");
        for (int i = 0; i < exp.length(); i++) {
             String str = exp.substring(i, i + 1);
             Operator op = getOperator(str);
             Operand od = getOperand(str);
             if (op != null) {
             if (!temp.isEmpty()) {
             list.add(temp);
             temp = "";
        }
        list.add(str);
        } else if (od != null) {
                 temp += str;
        } else {
          System.out.println("非法! ");
        return null;
        }
        }
        if (!temp.isEmpty()) {
            list.add(temp);
        }
        return list;
}
 private List<String> dealExpr(List<String> expList) {
        if(expList == null) {
             return null;
         }
         List<String> list = new LinkedList<String>();
         Stack<String> stack = new Stack<String>();
         for (String str : expList) {
             Operator op = getOperator(str.substring(0, 1));
             Operand od = getOperand(str.substring(0, 1));
             if (od != null) {
                 list.add(str);
             } else if (op != null) {
             if (Operator.PARENTHESIS_LEFT.equals(op)) {
                stack.push(str);
              } else if (Operator.PARENTHESIS_RIGHT.equals(op)) {
              while (true) {
                 if (stack.empty()) {
                     System.out.println("缺少左括号! ");
                     return null;
               }
               else if (Operator.PARENTHESIS_LEFT.operator.equals(stack.peek())) {
                    stack.pop();
              break;
               } else {
               list.add(stack.pop());
              }
       }
       } else {
        if (!stack.empty()) {
        Operator top_op = getOperator(stack.peek());
        //当前运算符优先级大于栈顶运算符优先级
        if(op.priority > top_op.priority
        || Operator.PARENTHESIS_LEFT.equals(top_op)) {
        stack.push(str);
        }
        //否则，将栈顶的运算符取出并存入队列，然后将自己入栈
        else {
        list.add(stack.pop());
        stack.push(str);
        }
        } else {
        stack.push(str);
        }
         }
        }
        }
        while(!stack.empty()) {
        String str = stack.peek();
        if(Operator.PARENTHESIS_LEFT.operator.equals(str)) {
         System.out.println("缺少右括号! ");
        return null;
        } else {
         list.add(stack.pop());
        }
        }
        return list;
}
private String operation(String x, String y, Operator op) {
         double a = 0.0;
         double b = 0.0;
         try {
                  a = Double.parseDouble(x);
                  b = Double.parseDouble(y);
         } catch (NumberFormatException e) {
                  System.out.println("操作数非法! ");
                  e.printStackTrace();
          }
            switch (op) {
            case ADD:
            return String.valueOf(a + b);
            case SUBTRACT:
            return String.valueOf(a - b);
            case MULTIPLY:
            return String.valueOf(a * b);
            case DIVIDE:
            return String.valueOf(a / b);
            case ABS:
            return String.valueOf(abs(a -  b));
            default:
            return null;
            }
}

public String calculate(String exp) {
        //System.out.println(exp);
        List<String> expList = dealExpr(resolveExpr(exp));
        if(expList == null) {
        return null;
        }
        Stack<String> stack = new Stack<String>();
        for(String str : expList) {
             Operator op = getOperator(str.substring(0, 1));
             Operand od = getOperand(str.substring(0, 1));
             if(od != null) {
                stack.push(str);
             } else if (op != null) {
                //目前仅针对二元运算符
                 String x = "";
                 String y = "";
                 if(!stack.empty()) {
                      y = stack.pop();
                 }
                 if(!stack.empty()) {
                      x = stack.pop();
                 }
                 if(!x.isEmpty() && !x.isEmpty()) {
                     String result = operation(x, y, op);
                 if(result == null) {
                     return null;
                 }
                 stack.push(result);
                 } else {
                     return null;
                 }
         }
        }
        return stack.pop();
}

public static void main(String[] args) {
            Calculator cal = new Calculator();
            String str = cal.calculate("1");
            System.out.println("运算结果:" + str);
}












        }
